package com.lord.otter.component.infrastructure.retry.domain.command;

import cn.hutool.core.lang.Assert;
import com.lord.otter.component.infrastructure.retry.constant.ExecModel;
import com.lord.otter.component.infrastructure.retry.constant.HttpMethod;
import lombok.Builder;
import lombok.Data;

import java.util.Objects;

/**
 * 添加http重试任务命令
 *
 * @author lord
 * 2025/8/16 23:43
 */
@Data
@Builder
public class AddHttpRetryTaskCommand {
    /**
     * 请求url
     */
    private String url;

    /**
     * 请求方法
     */
    private HttpMethod method;

    /**
     * 请求体
     */
    private String requestBody;

    /**
     * 请求头
     */
    private String headers;

    /**
     * 第一次执行错误信息(全堆栈)
     */
    private String firstExecError;

    /**
     * 调用策略
     */
    private ExecModel execModel;

    /**
     * 多久后重试(毫秒)
     * 第一次延迟时间
     */
    private Long delay;

    /**
     * 步长(毫秒)
     */
    private Long step;

    /**
     * N次幂 - 左位移 位数
     * com.lord.otter.infrastructure.retry.constant.ExecModel#POW_STEP时生效
     */
    private Integer pow;

    /**
     * 业务组
     */
    private String businessGroup;

    /**
     * 关联的业务id
     */
    private String businessId;

    /**
     * 最大重试次数
     */
    private Integer maxRetryNumber;

    /**
     * 成功回调的bean名称
     */
    private String callbackBeanName;

    public void check() {
        checkNull();
        if (delay <= 0) {
            throw new IllegalArgumentException("baseDelay必须大于0");
        }
        if (step != null && step <= 0) {
            throw new IllegalArgumentException("step必须大于0");
        }
        if (pow != null && pow <= 0) {
            throw new IllegalArgumentException("pow必须大于0");
        }
        if (maxRetryNumber <= 0) {
            throw new IllegalArgumentException("maxRetryNumber必须大于0");
        }
    }

    private void checkNull() {
        //所有字段不能为空
        Assert.notNull(url, "url不能为空");
        Assert.notNull(method, "method不能为空");
        Assert.notNull(execModel, "execModel不能为空");
        Assert.notNull(maxRetryNumber, "maxRetryNumber不能为空");
        Assert.notNull(businessGroup, "businessGroup不能为空");
        Assert.notNull(businessId, "businessId不能为空");
        Assert.notNull(delay, "delay不能为空");
        Assert.notNull(step, "step不能为空");
        if (Objects.requireNonNull(execModel) == ExecModel.POW_STEP) {
            Assert.notNull(pow, "pow不能为空");
        }
    }
}
